﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using XYS.Core.Models;

namespace XYS.Core.Api.Middlewares
{
    /// <summary>
    /// 自动ProducesResponseType特性
    /// </summary>
    public class ProduceResponseTypeModelProvider : IApplicationModelProvider
    {
        /// <summary>
        /// 优先级 排序
        /// </summary>
        public int Order => 0;

        /// <summary>
        /// Executing
        /// </summary>
        /// <param name="context"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnProvidersExecuting(ApplicationModelProviderContext context)
        {
            foreach (ControllerModel controller in context.Result.Controllers)
            {
                foreach (ActionModel action in controller.Actions)
                {
                    if (!action.Filters.Any(e => (e is ProducesResponseTypeAttribute producesResponseType) && producesResponseType.StatusCode == StatusCodes.Status200OK))
                    {
                        //返回类型为Task的话 取出其泛型 类型
                        Type returnType = action.ActionMethod.ReturnType;
                        if (typeof(Task).IsAssignableFrom(returnType))
                        {
                            returnType = returnType.GenericTypeArguments.FirstOrDefault();
                        }
                        if (returnType == null) continue;

                        if (!typeof(ResultModel).IsAssignableFrom(returnType))
                        {
                            if (returnType == typeof(IActionResult) || returnType == typeof(ActionResult) || returnType == typeof(void))
                            {
                                action.Filters.Add(new ProducesResponseTypeAttribute(typeof(ResultModel), StatusCodes.Status200OK));
                            }
                            else
                            {
                                Type type = typeof(ResultModel<>).MakeGenericType(returnType);
                                action.Filters.Add(new ProducesResponseTypeAttribute(type, StatusCodes.Status200OK));
                            }
                        }
                    }
                }
            }
        }



        /// <summary>
        /// Executed
        /// </summary>
        /// <param name="context"></param>
        public void OnProvidersExecuted(ApplicationModelProviderContext context) { }

    }
}
